package com.app.service.impl.user;

import com.app.domain.po.user.UserPo;
import com.app.domain.vo.user.UserVo;
import com.app.framework.config.QQAuthConfig;
import com.app.framework.utils.*;
import com.app.mapper.user.UserMapper;
import com.app.service.user.LoginService;
import com.app.service.user.UserCommonService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthQqRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;

/**
 * 登录方法实现
 */
@Service
public class LoginServiceImpl extends ServiceImpl<UserMapper, UserPo> implements LoginService {

    @Resource
    private QQAuthConfig qqAuthConfig;

    @Resource
    private UserCommonService userCommonService;

    /**
     * 第三方登录(获取跳转路径)
     */
    @Override
    public String qq(HttpServletResponse response) {
        AuthRequest authRequest = getAuthRequest();
        return authRequest.authorize(AuthStateUtils.createState());
    }

    /**
     * 第三方授权
     *
     * @param callback 第三方请求携带的参数
     * @param response 后端httpServlet响应
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void callback(AuthCallback callback, HttpServletResponse response) throws IOException {
        AuthRequest authRequest = getAuthRequest();
        AuthResponse<?> authResponse = authRequest.login(callback);
        AuthUser authUser = (AuthUser) authResponse.getData();
        String openId = authUser.getToken().getOpenId();
        String name = authUser.getNickname();
        String avatar = authUser.getAvatar();
        if (CollectionUtils.isNoNull(avatar) && avatar.startsWith("http://")) {
            avatar = avatar.replace("http://", "https://");
        }
        UserVo userVo = userCommonService.selectUserByOpenId(openId);
        if (CollectionUtils.isEmpty(userVo)) {
            //调用注册方法
            registerServer(openId, name, avatar);
            //调用登录方法
            loginServer(openId, response);
        } else {
            //调用登录方法
            loginServer(openId, response);
        }
        response.sendRedirect(qqAuthConfig.getHost());
    }

    /**
     * 退出登录
     */
    @Override
    public void out() {
        String token = TokenUtils.getToken();
        RedisUtils.del(token);
    }

    /**
     * 用于本地测试
     *
     * @param userId 用户ID
     */
    @Override
    public String localhost(Long userId) {
        //return null;
        UserPo userPo = baseMapper.selectById(userId);
        UserVo userVo = CoBeanUtils.copy(userPo, UserVo.class);
        String token = TokenUtils.saveToken(userVo.getId());
        RedisUtils.setToken(token, userVo);
        return token;
    }

    //--------------------------------------------------------|↓|公共方法|↓|----------------------------------------------------------
    //--------------------------------------------------------|↓|公共方法|↓|----------------------------------------------------------
    //--------------------------------------------------------|↓|公共方法|↓|----------------------------------------------------------

    /**
     * 鉴权方法
     */
    private AuthRequest getAuthRequest() {
        String clientId = qqAuthConfig.getClientId();
        String clientSecret = qqAuthConfig.getClientSecret();
        String redirectUri = qqAuthConfig.getRedirectUri();
        return new AuthQqRequest(AuthConfig.builder().clientId(clientId).clientSecret(clientSecret).redirectUri(redirectUri).build());
    }

    /**
     * 注册方法
     *
     * @param openId     用户openId
     * @param nickname   用户昵称
     * @param userAvatar 用户头像
     */
    public void registerServer(String openId, String nickname, String userAvatar) {
        String ip = IpUtils.getIp();
        HashMap<String, Object> cityInfo = IpUtils.getCityInfo(ip);
        UserPo userPo = new UserPo();
        userPo.setOpenId(openId);
        userPo.setName(nickname);
        userPo.setAvatar(userAvatar);
        userPo.setCreateTime(new Date());
        userPo.setLocation(cityInfo.get("province").toString() + "·" + cityInfo.get("isp").toString());
        baseMapper.insert(userPo);
        //删除缓存
        RedisUtils.concatDeletes("user::*");
    }

    /**
     * 登录方法
     *
     * @param openId openId
     */
    public void loginServer(String openId, HttpServletResponse response) {
        UserVo userVo = userCommonService.selectUserByOpenId(openId);
        UserPo userPo = CoBeanUtils.copy(userVo, UserPo.class);
        Boolean status = userPo.getStatus();
        Assert.state(status, "用户已被封禁");
        //登录时候删除Redis(旧)用户详情
        RedisUtils.del("user_details::" + userPo.getId());
        userPo.setLoginTime(new Date());
        baseMapper.updateById(userPo);
        //生成token
        String token = TokenUtils.saveToken(userVo.getId());
        //token存入Redis(24小时过期)
        RedisUtils.setToken(token, userVo);
    }

}